package cc.xiaolv123.vvvdjToBaidu.util;

import cc.xiaolv123.vvvdjToBaidu.vo.DJInfoVO;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.RuntimeUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class VvvdjUtil {
    @Value("${chromedriver}")
    private String chromedriver;

    @Value("${ffmpeg}")
    private String ffmpeg;

    @Value("${savepath}")
    private String savepath;

    OkHttpClient client = new OkHttpClient().newBuilder().build();
    /**
     * 根据页码采集
     *
     * @param type    采集类型 1华语Remix 2串烧舞曲 3慢歌连版 4外语Remix
     * @param pageNum 采集第几页
     * @return
     */
    public List<DJInfoVO> collectByPage(int type, int pageNum) {
        List<DJInfoVO> djInfoVOList = new ArrayList<>();
        Document pageDocument = null;
        try {
            String url = "";
            if (type == 1) {
                url = "https://www.vvvdj.com/sort/c3/0-0-0-0-" + pageNum + ".html";
            } else if (type == 2) {
                url = "https://www.vvvdj.com/sort/c1/0-0-0-0-" + pageNum + ".html";
            } else if (type == 3) {
                url = "https://www.vvvdj.com/sort/c2/0-0-0-0-" + pageNum + ".html";
            } else if (type == 4) {
                url = "https://www.vvvdj.com/sort/c4/0-0-0-0-" + pageNum + ".html";
            }
            log.info(url);
            Request request = new Request.Builder()
                    .url(url)
                    .method("GET", null)
                    .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0")
                    .build();
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                String result = response.body().string();
                pageDocument = Jsoup.parse(result);
                Elements musiclist = pageDocument.selectFirst(".list_musiclist").select("tr");
                for (int i = 1; i < musiclist.size(); i++) {
                    try {
                        Elements music = musiclist.get(i).select("td");
                        String id = music.get(1).text();
                        String name = music.get(2).selectFirst(".t1").selectFirst("a").text();
                        String time = music.get(2).selectFirst(".t2").selectFirst(".sc_1").text();
                        time = time.replaceAll("TIME ", "");
                        String size = music.get(2).selectFirst(".t2").selectFirst(".sc_2").text();
                        size = size.replaceAll("SIZE ", "");
                        String kbps = music.get(2).selectFirst(".t2").select(".sc_2").get(1).text();
                        DJInfoVO djInfoVO = new DJInfoVO();
                        djInfoVO.setId(id);
                        djInfoVO.setName(name);
                        djInfoVO.setSize(size);
                        djInfoVO.setKbps(kbps);
                        djInfoVO.setTime(time);
                        djInfoVO.setType(type);
                        djInfoVOList.add(djInfoVO);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
            ThreadUtil.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return djInfoVOList;
    }

    /**
     * 获取真实下载地址
     *
     * @param id
     * @param type 1华语Remix 2串烧舞曲 3慢歌连版 4外语Remix
     * @return
     */
    public String getRealDownloadUrl(String id, int type) {
        try {
            String result = null;
            if (type == 1 || type == 4) {
                Request request = new Request.Builder()
                        .url("http://tspc.vvvdj.com/sing/" + id + ".html")
                        .method("GET", null)
                        .addHeader("Host", "m.vvvdj.com")
                        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0")
                        .build();
                Response response = client.newCall(request).execute();
                if (response.isSuccessful()) {
                    result = response.body().string();
                }
            } else {
                Request request = new Request.Builder()
                        .url("http://tspc.vvvdj.com/play/" + id + ".html")
                        .method("GET", null)
                        .addHeader("Host", "m.vvvdj.com")
                        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0")
                        .build();
                Response response = client.newCall(request).execute();
                if (response.isSuccessful()) {
                    result = response.body().string();
                }
            }
            System.out.println(result);
            if (StrUtil.isNotBlank(result)) {
                String deCode = result.substring(result.indexOf("function DeCode() {"), result.indexOf("return h;")) + "return h; };}";
                String key = result.substring(result.indexOf("playurl=x."), result.indexOf("');", result.indexOf("playurl=x."))) + "');";
                key = key.substring(key.indexOf("('") + 2, key.indexOf("');"));
                String[] params = key.replaceAll("'", "").split(",");
                String deCodeFun = "\nfunction GetDataUrl() {\n" + "       var x = new DeCode();\n" + "       var playurl = x.O000O0OO0O0OO('" + params[0] + "','" + params[1] + "');\n" + "       return playurl;\n" + "   }";
                String out = "\t\t\tdocument.write(\"<p id='down'>\"+GetDataUrl()+\"</p>\")";
                String scriptStr = deCode + deCodeFun + out;
                return deCodeRealDownloadUrl(scriptStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private String deCodeRealDownloadUrl(String script) {
        System.setProperty("webdriver.chrome.driver", chromedriver);
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setHeadless(true);
        chromeOptions.addArguments("--no-sandbox");
        WebDriver webDriver = new ChromeDriver(chromeOptions);
        Object object = ((JavascriptExecutor) webDriver).executeScript(script);
        String down = webDriver.findElement(By.id("down")).getText();
        webDriver.quit();
        return down;
    }

    /**
     * 多视频拼接合并
     *
     * @param tsList 视频文件路径的List
     */
    public String mergeTsListToMp3(List<String> tsList, String id, String fileName) {
        String filePath = savepath + id + "/";
        String tempFileName = RandomUtil.randomNumbers(19);
        List<String> command1 = new ArrayList<>();
        command1.add(ffmpeg);
        command1.add("-i");
        StringBuffer buffer = new StringBuffer("\"concat:");
        for (int i = 0; i < tsList.size(); i++) {
            buffer.append(tsList.get(i));
            if (i != tsList.size() - 1) {
                buffer.append("|");
            } else {
                buffer.append("\"");
            }
        }
        command1.add(String.valueOf(buffer));
        command1.add("-c");
        command1.add("copy");
        command1.add(filePath + tempFileName + ".ts");
        commandStart(command1);

        List<String> command2 = new ArrayList<>();
        command2.add(ffmpeg);
        command2.add("-i");
        command2.add(filePath + tempFileName + ".ts");
        command2.add("-ar 44100");
        command2.add("-ac 2");
        command2.add("-ab 320k");
        command2.add("-vol 200");
        command2.add("-f mp3");
        command2.add(filePath + tempFileName + ".mp3");
        commandStart(command2);
        FileUtil.move(FileUtil.newFile(filePath + tempFileName + ".mp3"), FileUtil.newFile(filePath + fileName + ".mp3"), true);
        tsList.stream().forEach(x -> {
            FileUtil.del(x);
        });
        FileUtil.del(filePath + tempFileName + ".ts");
        FileUtil.del(filePath + tempFileName + ".mp3");
        return filePath + fileName + ".mp3";
    }

    /**
     * 调用命令行执行
     *
     * @param command 命令行参数
     */
    private void commandStart(List<String> command) {
        String commandStr = "";
        for (String v : command) {
            commandStr += v + " ";
        }
        log.info(commandStr);
        String s = RuntimeUtil.execForStr(commandStr);
        log.info(s);
    }

    public String[] getM3u8Info(String id, int type) throws IOException {
        String realDownloadUrl = getRealDownloadUrl(id, type);
        Request request = new Request.Builder()
                .url(realDownloadUrl)
                .method("GET", null)
                .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0")
                .build();
        Response response = client.newCall(request).execute();
        if (response.isSuccessful()) {
            String result = response.body().string();
            return new String[]{id, result, realDownloadUrl};
        }
        return null;
    }

    public List<String> getTsList(String id, String m3u8Info, String realDownloadUrl) throws IOException {
        String filePath = savepath + id + "/";
        FileUtil.del(filePath);
        FileUtil.mkdir(filePath);
        List<String> tsList = new ArrayList<>();
        List<String> realDownloadUrlSplit = StrUtil.split(realDownloadUrl, "/");
        String host = "";
        for (int i = 0; i < realDownloadUrlSplit.size() - 1; i++) {
            host += realDownloadUrlSplit.get(i) + "/";
        }
        List<String> m3u8List = StrUtil.split(m3u8Info, "\n");
        int count = 1;
        for (int i = 0; i < m3u8List.size(); i++) {
            String x = m3u8List.get(i);
            if (x.contains(".ts")) {
                Request request = new Request.Builder()
                        .url(realDownloadUrl)
                        .method("GET", null)
                        .addHeader("Host", "m.vvvdj.com")
                        .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0")
                        .build();
                Response response = client.newCall(request).execute();
                if (response.isSuccessful()) {
                    byte[] bytes = response.body().bytes();
                    String fileName = filePath + count + ".ts";
                    FileUtil.writeBytes(bytes, fileName);
                    tsList.add(fileName);
                }
                count++;
            }
        }
        return tsList;
    }

    public void downloadToDisk(DJInfoVO djInfoVO) throws IOException {
        Integer type = djInfoVO.getType();
        String id = djInfoVO.getId();
        String name = djInfoVO.getName();
        String[] m3u8Info = getM3u8Info(id, type);
        List<String> tsList = getTsList(m3u8Info[0], m3u8Info[1], m3u8Info[2]);
        mergeTsListToMp3(tsList, id, name);
    }
}
